﻿using System;
using System.Collections.Generic;
using System.Text;

using ShootSearch.FileSystem;
using ShootSearch.Parsers;
using ShootSearch.Core;
using System.Collections;
using ShootSearch.Util;
using System.Diagnostics;
using ShootSearch.Logging;

namespace ShootSearch.Jobs
{
    public class ParserJob: InputOutputJob
    {
        public const string OUTPUT_PATH = "Output";

        protected ParserJobConfig config;
        protected IFileSystem outputFile;
        protected Dictionary<string, List<IParser>> parsers = null;

        #region IConfigable Members
        public override SpiderManConfig Config
        {
            get
            {
                return config;
            }
            set
            {
                if (value is ParserJobConfig)
                {
                    base.Config = value;
                    config = value as ParserJobConfig;
                }

            }
        } 
        #endregion

        public ParserJob()
        {
            config = new ParserJobConfig();  
        }

        protected override InputOutputArgument InitializeArgument()
        {
            SetOutputPath();
            return base.InitializeArgument();
        }

        #region InitializeProgress
        protected override bool InitializeProgress()
        {
            if (config == null) return false;
            if (!base.InitializeProgress()) return false;

            outputFile = config.Output.GetObjectWithConfig() as IFileSystem;
            if (outputFile == null) return false;

            #region Load Filters
            parsers = new Dictionary<string, List<IParser>>();
            foreach (AssemblyWithConfig filter in config.Parsers)
            {
                IParser ifilter = filter.GetObjectWithConfig() as IParser;
                if (ifilter != null)
                {
                    ifilter.Logger = this.Logger;
                    List<string> list = ifilter.ContentType;

                    foreach (string contentType in list)
                    {
                        List<IParser> filterList = new List<IParser>();
                        if (parsers.ContainsKey(contentType))
                        {
                            filterList = parsers[contentType];
                        }
                        filterList.Add(ifilter);
                        parsers[contentType] = filterList;
                    }
                }
            }

            if (parsers.Count == 0)
            {
                Log.Error(Logger, "No Parser in working,,,");
                return false;

            }
            #endregion


            return true;
        }

        private void SetOutputPath()
        {
            if (config.OutputArgument == null) config.OutputArgument = new InputOutputArgument();
            if (string.IsNullOrEmpty(config.OutputArgument.Path))
            {
                config.OutputArgument.Path = IO.FormatDirName(contextPath + OUTPUT_PATH);
            }
            SetNextJobParameters(InputOutputJob.INPUT_PATH, config.OutputArgument.Path);
        } 
        #endregion

        #region Process FSID

        protected override bool BeforeProcessFSID(InputOutputArgument arg)
        {
            bool inputOk = base.BeforeProcessFSID(arg);

           

            if (string.IsNullOrEmpty(config.OutputArgument.FSID))
            {
                outputFile.FSID = arg.FSID;
            }
            else
            {
                outputFile.FSID = config.OutputArgument.FSID;
            }

            bool outputOK = outputFile.CreateOpen(config.OutputArgument.Path);

            return inputOk && outputOK;


        }

        protected override void ProcessDocument(ShootSearch.FileSystem.IFileObject doc)
        {
            List<IParser> list = null;
            if (parsers.ContainsKey(doc.ContentType))
            {
                list = parsers[doc.ContentType];
            }
            else if (parsers.ContainsKey("*/*"))
            {
                list = parsers["*/*"];
            }
            if (list == null) return;

            IFileObject docOutput = null;
            for (int j = 0; j < list.Count; j++)
            {
                if (list[j].Parse(doc, out docOutput))
                {
                    Log.Info(Logger, "Parse: " + doc.Url);
                    //Trace.WriteLine("Parse: " + doc.Url);
                    break;
                }
            }
            if (docOutput != null)
            {
                outputFile.Write(docOutput);
            }

        }

        protected override void AfterProcessFSID(InputOutputArgument arg)
        {
            if (outputFile != null) outputFile.Close();
        } 
        #endregion

        #region Launch Next
        protected override Hashtable GetNextArgument(InputOutputArgument arg)
        {
            Hashtable args = base.GetNextArgument(arg);
            args.Add(InputOutputJob.INPUT_PATH, this.config.OutputArgument.Path);
            args.Add(InputOutputJob.INPUT_FSID, arg.FSID);
            return args;
        } 
        #endregion

        #region IDisposable Members
        public override void Dispose()
        {
            base.Dispose();
            if (outputFile != null) outputFile.Close();

        } 
        #endregion

       
    }
}
